package com.och.mrcp.core.sip.model;

import lombok.Data;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.nio.charset.StandardCharsets;

/**
 * SIP消息基类
 * RFC 3261 - SIP: Session Initiation Protocol
 */
@Data
public abstract class SipMessage {
    
    protected String startLine;
    protected Map<String, String> headers = new HashMap<>();
    protected String body;
    protected String rawMessage;
    
    // RFC 3261 必需头部字段
    protected String callId;
    protected String cseq;
    protected String from;
    protected String to;
    protected String via;
    protected String contact;
    protected String contentType;
    protected int contentLength;
    
    // RFC 3261 可选头部字段
    protected String maxForwards;
    protected String userAgent;
    protected String expires;
    protected String sessionExpires;
    protected String minSessionExpires;
    
    public SipMessage() {
        // 生成默认的Call-ID (RFC 3261 Section 8.1.1.4)
        this.callId = UUID.randomUUID().toString();
        this.maxForwards = "70"; // RFC 3261 Section 8.1.1.1
    }
    
    /**
     * 添加头部字段 (RFC 3261 Section 7.3)
     * 头部名称不区分大小写，但值区分大小写
     */
    public void addHeader(String name, String value) {
        if (name == null || value == null) {
            throw new IllegalArgumentException("Header name and value cannot be null");
        }
        headers.put(name.toLowerCase(), value);
    }
    
    /**
     * 获取头部字段值
     */
    public String getHeader(String name) {
        if (name == null) {
            return null;
        }
        return headers.get(name.toLowerCase());
    }
    
    /**
     * 设置头部字段值
     */
    public void setHeader(String name, String value) {
        if (name == null || value == null) {
            throw new IllegalArgumentException("Header name and value cannot be null");
        }
        headers.put(name.toLowerCase(), value);
    }
    
    /**
     * 移除头部字段
     */
    public void removeHeader(String name) {
        if (name != null) {
            headers.remove(name.toLowerCase());
        }
    }
    
    /**
     * 检查是否包含指定头部
     */
    public boolean hasHeader(String name) {
        return name != null && headers.containsKey(name.toLowerCase());
    }
    
    /**
     * 获取所有头部字段
     */
    public Map<String, String> getAllHeaders() {
        return new HashMap<>(headers);
    }
    
    /**
     * 设置必需头部字段
     */
    public void setRequiredHeaders(String from, String to, String via) {
        this.from = from;
        this.to = to;
        this.via = via;
        
        // 添加到headers map
        if (from != null) addHeader("From", from);
        if (to != null) addHeader("To", to);
        if (via != null) addHeader("Via", via);
        if (callId != null) addHeader("Call-ID", callId);
        if (cseq != null) addHeader("CSeq", cseq);
        if (maxForwards != null) addHeader("Max-Forwards", maxForwards);
    }
    
    /**
     * 设置内容相关头部
     */
    public void setContentHeaders(String contentType, String body) {
        this.contentType = contentType;
        this.body = body;
        this.contentLength = body != null ? body.length() : 0;
        
        if (contentType != null) addHeader("Content-Type", contentType);
        addHeader("Content-Length", String.valueOf(contentLength));
    }
    
    public abstract String getMethod();
    
    public abstract boolean isRequest();
    
    public abstract boolean isResponse();
    
    /**
     * 将消息编码为原始SIP消息格式 (RFC 3261 Section 7.4)
     */
    public String toRawMessage() {
        StringBuilder sb = new StringBuilder();
        
        // Start line (RFC 3261 Section 7.1)
        sb.append(startLine).append("\r\n");
        
        // Headers (RFC 3261 Section 7.3)
        // 按照RFC 3261建议的顺序排列头部
        addStandardHeaders(sb);
        
        // Empty line (RFC 3261 Section 7.4)
        sb.append("\r\n");
        
        // Body (RFC 3261 Section 7.4)
        if (body != null && !body.isEmpty()) {
            sb.append(body);
        }
        
        return sb.toString();
    }
    
    /**
     * 同步内容相关头部，确保Content-Type和Content-Length正确
     */
    public void synchronizeContentHeaders() {
        // 如果存在body，根据字节长度更新Content-Length
        int length = 0;
        if (body != null) {
            length = body.getBytes(StandardCharsets.UTF_8).length;
        }
        this.contentLength = length;
        setHeader("Content-Length", String.valueOf(length));
        // 如果设置了contentType，则确保对应头存在
        if (contentType != null && !contentType.isEmpty()) {
            setHeader("Content-Type", contentType);
        }
    }
    
    /**
     * 按照RFC 3261建议的顺序添加标准头部
     */
    private void addStandardHeaders(StringBuilder sb) {
        // 必需头部
        if (via != null) sb.append("Via: ").append(via).append("\r\n");
        if (from != null) sb.append("From: ").append(from).append("\r\n");
        if (to != null) sb.append("To: ").append(to).append("\r\n");
        if (callId != null) sb.append("Call-ID: ").append(callId).append("\r\n");
        if (cseq != null) sb.append("CSeq: ").append(cseq).append("\r\n");
        if (maxForwards != null) sb.append("Max-Forwards: ").append(maxForwards).append("\r\n");
        
        // 可选头部
        if (contact != null) sb.append("Contact: ").append(contact).append("\r\n");
        if (userAgent != null) sb.append("User-Agent: ").append(userAgent).append("\r\n");
        if (expires != null) sb.append("Expires: ").append(expires).append("\r\n");
        if (sessionExpires != null) sb.append("Session-Expires: ").append(sessionExpires).append("\r\n");
        if (minSessionExpires != null) sb.append("Min-Session-Expires: ").append(minSessionExpires).append("\r\n");
        
        // 内容头部
        if (contentType != null) sb.append("Content-Type: ").append(contentType).append("\r\n");
        sb.append("Content-Length: ").append(contentLength).append("\r\n");
        
        // 其他自定义头部
        for (Map.Entry<String, String> entry : headers.entrySet()) {
            String name = entry.getKey();
            String value = entry.getValue();
            
            // 跳过已经添加的标准头部
            if (!isStandardHeader(name)) {
                sb.append(capitalizeHeaderName(name)).append(": ").append(value).append("\r\n");
            }
        }
    }
    
    /**
     * 检查是否为标准头部
     */
    private boolean isStandardHeader(String name) {
        String[] standardHeaders = {
            "via", "from", "to", "call-id", "cseq", "max-forwards",
            "contact", "user-agent", "expires", "session-expires", "min-session-expires",
            "content-type", "content-length"
        };
        
        for (String header : standardHeaders) {
            if (header.equals(name.toLowerCase())) {
                return true;
            }
        }
        return false;
    }
    
    /**
     * 将头部名称首字母大写 (RFC 3261 Section 7.3)
     */
    private String capitalizeHeaderName(String name) {
        if (name == null || name.isEmpty()) {
            return name;
        }
        return name.substring(0, 1).toUpperCase() + name.substring(1).toLowerCase();
    }
}
